﻿
// InjectorDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "Injector.h"
#include "InjectorDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

FnRtlEncodeRemotePointer _RtlEncodeRemotePointer;
FnRtlDecodeRemotePointer _RtlDecodeRemotePointer;
FnSetProcessValidCallTargets _SetProcessValidCallTargets;

void TriggerCtrlC(HWND hWindow)
{
    INPUT ip;
    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0;
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;
    ip.ki.wVk = VK_CONTROL;
    ip.ki.dwFlags = 0; //0 for keypress
    SendInput(1, &ip, sizeof(INPUT));
    Sleep(300);
    PostMessage(hWindow, WM_KEYDOWN, 0x43, 0);
    Sleep(300);
    ip.ki.dwFlags = 2; //2 for keyup (we want this, as we don't want to keep a system wide CTRL down)
    SendInput(1, &ip, sizeof(INPUT));

}


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CInjectorDlg 对话框



CInjectorDlg::CInjectorDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_INJECTOR_DIALOG, pParent)
    , m_dwProcessId(0)
    , m_strDllPath(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pSetConsoleCtrlHandler = nullptr;
}

void CInjectorDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT_PROCESSID, m_dwProcessId);
    DDX_Control(pDX, IDC_LIST_MODULE, m_ModuleList);
    DDX_Text(pDX, IDC_EDIT_DLL_BROWSE, m_strDllPath);
    DDX_Control(pDX, IDC_EDIT_DLL_BROWSE, m_DllBrowseCtrl);
}

BEGIN_MESSAGE_MAP(CInjectorDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BTN_TRAVERSE_MODULE, &CInjectorDlg::OnBnClickedBtnTraversemodules)
    ON_BN_CLICKED(IDC_BTN_SELECTPROCESS, &CInjectorDlg::OnBnClickedBtnSelectprocess)
    ON_MESSAGE(WM_PROCESSID, &CInjectorDlg::OnRecvProcessId)
    ON_MESSAGE(WM_PROCESSIMAGE, &CInjectorDlg::OnRecvProcessImage)
    ON_MESSAGE(WM_MODULEINJECT, &CInjectorDlg::OnRecvInjectConfig)
    ON_MESSAGE(WM_SHELLCODEINJECT, &CInjectorDlg::OnRecvShellCodeConfig)
    ON_MESSAGE(WM_CODEINJECTTYPE, &CInjectorDlg::OnRecvShellCodeType)
    ON_MESSAGE(WM_GETINJECTADDRESS, &CInjectorDlg::OnSendCodeInjectAddress)
    ON_WM_DROPFILES()
    ON_BN_CLICKED(IDC_BTN_DLLINJECT, &CInjectorDlg::OnBnClickedBtnInject)
    ON_NOTIFY(NM_RCLICK, IDC_LIST_MODULE, &CInjectorDlg::OnNMRClickListModule)
    ON_COMMAND(ID_RIGHTMENU_REFRESHLIST, &CInjectorDlg::OnRightmenuRefreshlist)
    ON_COMMAND(ID_RIGHTMENU_REMOVEMODULE, &CInjectorDlg::OnRightmenuRemovemodule)
    ON_BN_CLICKED(IDC_BTN_SHELLCODEINJECT, &CInjectorDlg::OnBnClickedBtnShellcodeinject)
END_MESSAGE_MAP()


// CInjectorDlg 消息处理程序

BOOL CInjectorDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码


    //
    //  设置标题
    //

    CString strTitle;
#ifdef _WIN64
    strTitle = _T("Injector x64");
#else
    strTitle = _T("Injector x86");
#endif
    this->SetWindowText(strTitle);

    //
    //  申请内存
    //  用于接收用户选择的注入方式
    //

    m_pInjectConfig = (PINJECT_CONFIG)(new char[sizeof(INJECT_CONFIG)]);
    m_pShellCodeConfig = (PSHELLCODE_CONFIG)(new char[sizeof(SHELLCODE_CONFIG)]);
    if (!m_pInjectConfig || !m_pShellCodeConfig)
    {
        AfxMessageBox(_T("系统资源不足"));
        ExitProcess(0);
    }
    RtlZeroMemory(m_pInjectConfig, sizeof(INJECT_CONFIG));
    RtlZeroMemory(m_pShellCodeConfig, sizeof(SHELLCODE_CONFIG));

    //
    //  模块列表初始化
    //

    m_ModuleList.InsertColumn(0, L"模块名称", 0, 100);
    m_ModuleList.InsertColumn(1, L"模块基址", 0, 80);
    m_ModuleList.InsertColumn(2, L"模块大小", 0, 100);
    m_ModuleList.InsertColumn(3, L"模块路径", 0, 320);
    m_ModuleList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_FLATSB);

    //
    //  文件拖拽初始化
    //

    DragAcceptFiles(TRUE);
    ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
    ChangeWindowMessageFilter(SPI_SETANIMATION, MSGFLT_ADD);

    //
    //  设置打开文件对话框属性
    //

    m_DllBrowseCtrl.EnableFileBrowseButton(_T(""), _T("DLL (*.dll)|*.dll|All Files (*.*)|*.*||"));

    m_CodeInjectType = S_REMOTE_THREAD;

    m_lpCodeAddress = nullptr;

	return TRUE;
}

void CInjectorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CInjectorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CInjectorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CInjectorDlg::InitializeModuleList()
{
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32 = { 0 };
    CString str;
    int nItem = 0;

    do
    {
        //
        //  获取模块快照句柄
        //

        hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, m_dwProcessId);
        if (INVALID_HANDLE_VALUE == hSnapShot) break;

        //
        //  获取第一个模块信息
        //

        me32.dwSize = sizeof(MODULEENTRY32);
        if (!Module32First(hSnapShot, &me32)) break;

        do
        {
            str = me32.szModule;
            m_ModuleList.InsertItem(nItem, str);
            str.Format(_T("%p"), me32.modBaseAddr);
            m_ModuleList.SetItemText(nItem, 1, str);
            str.Format(_T("%d"), me32.modBaseSize);
            m_ModuleList.SetItemText(nItem, 2, str);
            str = me32.szExePath;
            m_ModuleList.SetItemText(nItem, 3, str);
            nItem++;
        } while (Module32Next(hSnapShot, &me32));

    } while (FALSE);

    if (INVALID_HANDLE_VALUE != hSnapShot)
        CloseHandle(hSnapShot);
}

PVOID CInjectorDlg::GetFunctionAddress(const char* DllName, const char* FunctionName)
{
    PVOID Address = nullptr;
    HMODULE hModule;

    do
    {
        hModule = GetModuleHandleA(DllName);
        if (!hModule) break;

        Address = GetProcAddress(hModule, FunctionName);

    } while (FALSE);

    return Address;
}

DWORD CInjectorDlg::GetImageSize(IN LPVOID PeBase)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)PeBase;
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((LongPtr)PeBase + pDosHeader->e_lfanew);
    return pNtHeaders->OptionalHeader.SizeOfImage;
}

void CInjectorDlg::SetImageBase(IN LPVOID PeBase, IN LongPtr ImageBase)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)PeBase;
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((LongPtr)PeBase + pDosHeader->e_lfanew);
    DWORD dwOldAttribute;
    LPVOID lpAddress = (LPVOID)(pNtHeaders->OptionalHeader.ImageBase);

    VirtualProtect(lpAddress, sizeof(LongPtr), PAGE_READWRITE, &dwOldAttribute);
    pNtHeaders->OptionalHeader.ImageBase = ImageBase;
    VirtualProtect(lpAddress, sizeof(LongPtr), dwOldAttribute, &dwOldAttribute);
}

#ifndef _WIN64

#define PEB_OFFSET  0x30
#define LDR_OFFSET  0x0C
#define LIST_OFFSET 0x1C
#define BASE_OFFSET 0x08
#define BUFF_OFFSET 0x20
#define NUM_OFFSET  0x0C

#else

#define PEB_OFFSET  0x60
#define LDR_OFFSET  0x18
#define LIST_OFFSET 0x30
#define BASE_OFFSET 0x10
#define BUFF_OFFSET 0x40
#define NUM_OFFSET  0x0C

#endif

typedef FARPROC* (WINAPI* FnGetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
typedef HMODULE(WINAPI* FnLoadLibraryA)(LPCSTR lpLibFileName);
typedef BOOL(WINAPI* FnVirtualProtect)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
typedef void (WINAPI* FnExitThread)(DWORD dwExitCode);

typedef struct _REMOTE_PARAMS
{
    LongPtr ImageBase;
    FnGetProcAddress _GetProcAddress;
    FnLoadLibraryA _LoadLibraryA;
    FnVirtualProtect _VirtualProtect;
    FnExitThread _ExitThread;
}REMOTE_PARAMS, * PREMOTE_PARAMS;

DWORD RecoverIAT(IN LPVOID lpThreadParameter)
{
    PREMOTE_PARAMS Param = (PREMOTE_PARAMS)lpThreadParameter;
    FnGetProcAddress _GetProcAddress = Param->_GetProcAddress;
    FnLoadLibraryA _LoadLibraryA = Param->_LoadLibraryA;
    FnVirtualProtect _VirtualProtect = Param->_VirtualProtect;
    FnExitThread _ExitThread = Param->_ExitThread;
    LongPtr BaseOfImage = Param->ImageBase;
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)BaseOfImage;
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((LongPtr)pDosHeader + pDosHeader->e_lfanew);
    PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
        (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + BaseOfImage);

    while (pImportDirectory->Name)
    {
        PIMAGE_THUNK_DATA pIat = (PIMAGE_THUNK_DATA)(pImportDirectory->FirstThunk + BaseOfImage);
        PIMAGE_THUNK_DATA pInt = nullptr;

        if (0 != pImportDirectory->OriginalFirstThunk)
        {
            pInt = (PIMAGE_THUNK_DATA)(pImportDirectory->OriginalFirstThunk + BaseOfImage);
        }
        else
        {
            pInt = pIat;
        }

        HMODULE hModule = _LoadLibraryA((LPCSTR)(pImportDirectory->Name + BaseOfImage));

        PIMAGE_IMPORT_BY_NAME pName = nullptr;
        LPVOID pAddress = nullptr;
        while (pInt->u1.Function)
        {
            if (IMAGE_SNAP_BY_ORDINAL(pInt->u1.Ordinal))        // serial number
            {
                pAddress = _GetProcAddress(hModule, (LPCSTR)(pInt->u1.Ordinal & 0x7FFFFFFF));
            }
            else       // name string
            {
                pName = (PIMAGE_IMPORT_BY_NAME)(pInt->u1.AddressOfData + BaseOfImage);
                pAddress = _GetProcAddress(hModule, pName->Name);
            }

            DWORD dwOldAttribute = 0;
            _VirtualProtect(&pIat->u1.Function, sizeof(pIat->u1.Function), PAGE_READWRITE, &dwOldAttribute);
            pIat->u1.Function = (LongPtr)pAddress;
            _VirtualProtect(&pIat->u1.Function, sizeof(pIat->u1.Function), dwOldAttribute, &dwOldAttribute);

            pIat++;
            pInt++;
        }
        pImportDirectory++;
    }

    _ExitThread(0);

    return 0;
}

void RecoverRelocationEntry(LPVOID PeBase, LongPtr ImageBase, LongPtr PrevImageBase, DWORD RvaOfReloc, DWORD SizeOfReloc)
{
    LongPtr BaseOfImage = (LongPtr)PeBase;
    PIMAGE_BASE_RELOCATION pRelocTable = (PIMAGE_BASE_RELOCATION)((LongPtr)BaseOfImage + RvaOfReloc);

    while (pRelocTable->SizeOfBlock != 0)
    {
        if (0xFDFDFDFD == pRelocTable->VirtualAddress) break;

        DWORD dwSize = pRelocTable->SizeOfBlock;
        DWORD dwCount = (pRelocTable->SizeOfBlock - 8) / 2;
        DWORD dwRva = pRelocTable->VirtualAddress;
        PWORD pwEntry = (PWORD)(pRelocTable + 1);

        for (DWORD i = 0; i < dwCount; i++)
        {
            WORD wVal = *pwEntry;
#ifndef _WIN64
            if (!(((wVal & 0xF000) >> 12) == 3)) { pwEntry++; continue; }
#endif
            DWORD dwOffset = 0;
            dwOffset = wVal & 0x0FFF;
            LongPtr* pRecoverAddress = (LongPtr*)((LongPtr)BaseOfImage + dwRva + dwOffset);

            DWORD dwOldAttribute = 0;
            VirtualProtect(pRecoverAddress, sizeof(LongPtr), PAGE_READWRITE, &dwOldAttribute);
            *pRecoverAddress = *pRecoverAddress - PrevImageBase + ImageBase;
            VirtualProtect(pRecoverAddress, sizeof(LongPtr), dwOldAttribute, &dwOldAttribute);

            pwEntry++;
        }
        pRelocTable = (PIMAGE_BASE_RELOCATION)((LongPtr)pRelocTable + dwSize);
    }
}

PIMAGE_SECTION_HEADER FindSectionByName(const char* SectionName, const PIMAGE_NT_HEADERS NtHeaders)
{
    if (!SectionName) return nullptr;

    PIMAGE_SECTION_HEADER pFirstSection = nullptr;
    PIMAGE_NT_HEADERS pNtHeaders = nullptr;
    char strName[IMAGE_SIZEOF_SHORT_NAME] = { 0 };

    pFirstSection = IMAGE_FIRST_SECTION(NtHeaders);
    pNtHeaders = NtHeaders;

    if (strlen(SectionName) > IMAGE_SIZEOF_SHORT_NAME) return nullptr;
    memcpy(strName, SectionName, IMAGE_SIZEOF_SHORT_NAME);

    for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++)
    {
        if (!strcmp(strName, (char*)(pFirstSection[i].Name))) return pFirstSection + i;
    }

    return nullptr;
}

LPVOID CInjectorDlg::RelocateImage(IN LPVOID PeBase, IN DWORD ImageSize, IN LongPtr ImageBase)
{
    LPVOID lpAddress = nullptr;
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)PeBase;
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((char*)PeBase + pDosHeader->e_lfanew);
    DWORD dwRvaOfReloc;
    DWORD dwSizeOfReloc;
    LongPtr PrevImageBase = pNtHeaders->OptionalHeader.ImageBase;

    do
    {
        //
        //  设置映像基址
        //

        SetImageBase(PeBase, ImageBase);

        dwRvaOfReloc = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
        dwSizeOfReloc = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

        //
        //  申请内存
        //

        lpAddress = VirtualAlloc(nullptr, ImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!lpAddress) break;
        RtlCopyMemory(lpAddress, PeBase, ImageSize);

        if (!dwRvaOfReloc || !dwSizeOfReloc) break;

        //
        //  修复重定位表
        //

        RecoverRelocationEntry(lpAddress, ImageBase, PrevImageBase, dwRvaOfReloc, dwSizeOfReloc);

    } while (FALSE);

    return lpAddress;
}

BOOL CInjectorDlg::GetRvaOfTextAndSize(IN LPVOID PeBase, IN OUT PDWORD RvaOfText, IN OUT PDWORD SizeOfText)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)PeBase;
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((char*)PeBase + pDosHeader->e_lfanew);
    PIMAGE_SECTION_HEADER pTextSection = FindSectionByName(".text", pNtHeaders);

    if (!pTextSection) return FALSE;

    *RvaOfText = pTextSection->VirtualAddress;
    *SizeOfText = pTextSection->Misc.VirtualSize;

    return TRUE;
}

DWORD CInjectorDlg::GetRvaOfEntryPoint(IN LPVOID PeBase)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)PeBase;
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((char*)PeBase + pDosHeader->e_lfanew);
    return pNtHeaders->OptionalHeader.AddressOfEntryPoint;
}

BOOL CInjectorDlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN)
    {
        switch (pMsg->wParam)
        {
        case VK_ESCAPE:
            return TRUE;
        case VK_RETURN:
            return TRUE;
        default:
            break;
        }
    }

    return CDialogEx::PreTranslateMessage(pMsg);
}

BOOL CInjectorDlg::EnumWindowsProcAdapter(IN HWND hwnd, IN LPARAM lParam)
{
    return ((CInjectorDlg*)lParam)->EnumWindowsProc(hwnd, 0);
}

BOOL CInjectorDlg::EnumWindowsProc(IN HWND hwnd, IN LPARAM lParam)
{
    BOOL bRet = TRUE;
    DWORD dwProcessId;
    GetWindowThreadProcessId(hwnd, &dwProcessId);

    if (dwProcessId == m_dwProcessId && (::GetWindow(hwnd, GW_OWNER) == (HWND)0 && ::IsWindowVisible(hwnd)))
    {
        bRet = FALSE;
        m_hMainWindow = hwnd;
    }

    return bRet;
}

void CInjectorDlg::OnBnClickedBtnTraversemodules()
{
    m_ModuleList.DeleteAllItems();
    UpdateData(TRUE);
    InitializeModuleList();
}


void CInjectorDlg::OnBnClickedBtnSelectprocess()
{
    m_ProcessDlg.DoModal();
    OnBnClickedBtnTraversemodules();
}

LRESULT CInjectorDlg::OnRecvProcessId(WPARAM wParam, LPARAM lParam)
{
    m_dwProcessId = (DWORD)wParam;
    UpdateData(FALSE);
    return 0;
}

LRESULT CInjectorDlg::OnRecvProcessImage(WPARAM wParam, LPARAM lParam)
{
    if (wParam)
    {
        CString* m_ProcessImage = (CString*)wParam;
        m_strProcessImage = *m_ProcessImage;
    }
    else
    {
        m_strProcessImage.Empty();
    }

    return 0;
}

LRESULT CInjectorDlg::OnRecvInjectConfig(WPARAM wParam, LPARAM lParam)
{
    if (wParam)
    {
        RtlCopyMemory(m_pInjectConfig, (PINJECT_CONFIG)wParam, sizeof(INJECT_CONFIG));
        m_ModuleInjectType = m_pInjectConfig->Type;

        if (m_ModuleInjectType == M_MESSAGE_HOOK)
        {
            char* ptr = new char[m_pInjectConfig->DataLen + 1];
            if (!ptr) goto _None;
            RtlZeroMemory(ptr, m_pInjectConfig->DataLen + 1);
            RtlCopyMemory(ptr, m_pInjectConfig->Data, m_pInjectConfig->DataLen);
            m_pInjectConfig->Data = ptr;
        }
    }
    else
    {
_None:
        RtlZeroMemory(m_pInjectConfig, sizeof(INJECT_CONFIG));
    }

    return 0;
}

LRESULT CInjectorDlg::OnRecvShellCodeConfig(WPARAM wParam, LPARAM lParam)
{
    PSHELLCODE_CONFIG pConfig = (PSHELLCODE_CONFIG)wParam;
    char* pCode = nullptr;

    do
    {
        if (!pConfig) break;

        pCode = new char[pConfig->CodeLen];
        if (!pCode) break;

        RtlCopyMemory(m_pShellCodeConfig, pConfig, sizeof(SHELLCODE_CONFIG));
        RtlCopyMemory(pCode, pConfig->Code, pConfig->CodeLen);
        m_pShellCodeConfig->Code = pCode;

        return 0;

    } while (FALSE);

    RtlZeroMemory(m_pShellCodeConfig, sizeof(SHELLCODE_CONFIG));
    return 0;
}

LRESULT CInjectorDlg::OnRecvShellCodeType(WPARAM wParam, LPARAM lParam)
{
    m_CodeInjectType = (SHELLCODE_INJECT)wParam;
    return 0;
}

LRESULT CInjectorDlg::OnSendCodeInjectAddress(WPARAM wParam, LPARAM lParam)
{
    ::SendMessage((HWND)wParam, WM_GETINJECTADDRESS, (WPARAM)m_lpCodeAddress, 0);
    return 0;
}


void CInjectorDlg::OnDropFiles(HDROP hDropInfo)
{
    TCHAR szFilePath[MAX_PATH];
    DragQueryFile(hDropInfo, 0, szFilePath, sizeof(szFilePath));
    SetDlgItemText(IDC_EDIT_DLL_BROWSE, szFilePath);
    DragFinish(hDropInfo);
    UpdateData(TRUE);

    CDialogEx::OnDropFiles(hDropInfo);
}

void CInjectorDlg::RemoteThreadInject()
{
    UpdateData(TRUE);

    if (m_strDllPath.IsEmpty())
    {
        AfxMessageBox(_T("请选择模块"));
        return;
    }

    HANDLE hProcess = nullptr;
    LPVOID pVa = nullptr;
    BSTR strModulePath;
    SIZE_T BytesWritten = 0;
    BOOL bRet;
    HANDLE hRemoteThread = nullptr;
    BOOL bSuccess = FALSE;

    do
    {

        //
        //  获得目标进程句柄
        //

        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
        if (!hProcess) break;

        //
        //  申请虚拟内存空间
        //

        pVa = VirtualAllocEx(hProcess, nullptr, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if (!pVa) break;

        //
        //  写入模块的绝对路径
        //

        strModulePath = m_strDllPath.AllocSysString();
        bRet = WriteProcessMemory(hProcess, pVa, strModulePath, ((wcslen(strModulePath) + 1) * 2), &BytesWritten);
        ::SysFreeString(strModulePath);
        if (!bRet) break;

        //
        //  远程线程注入
        //

        hRemoteThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, pVa, 0, nullptr);
        WaitForSingleObject(hRemoteThread, 1000);

        bSuccess = TRUE;

    } while (FALSE);

    if (hRemoteThread)
        CloseHandle(hRemoteThread);

    if (pVa)
        VirtualFreeEx(hProcess, pVa, 0x100, MEM_RELEASE);

    if (hProcess)
        CloseHandle(hProcess);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));

    RefreshModuleList();
}

void CInjectorDlg::RemoteThreadInjectX86()
{
}

void CInjectorDlg::UserApcInject()
{
    UpdateData(TRUE);

    if (m_strDllPath.IsEmpty()) 
    { 
        AfxMessageBox(_T("请选择模块")); 
        return; 
    }

    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    THREADENTRY32 te32 = { 0 };
    HANDLE hThread = nullptr;
    HANDLE hProcess = nullptr;
    LPVOID pVa = nullptr;
    SIZE_T BytesWritten;
    BOOL bRet;
    BSTR strModulePath = nullptr;
    BOOL bSuccess = FALSE;

    do
    {
        //
        //  获取线程快照句柄
        //

        hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
        if (hSnapShot == INVALID_HANDLE_VALUE) break;

        //
        //  获取第一个线程信息
        //

        te32.dwSize = sizeof(THREADENTRY32);
        if (!Thread32First(hSnapShot, &te32)) break;

        //
        //  获取指定进程句柄
        //

        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
        if (!hProcess) break;

        //
        //  申请内存，并写入模块路径
        //

        pVa = VirtualAllocEx(hProcess, nullptr, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if (!pVa) break;
        strModulePath = m_strDllPath.AllocSysString();
        bRet = WriteProcessMemory(hProcess, pVa, strModulePath, ((wcslen(strModulePath) + 1) * 2), &BytesWritten);
        ::SysFreeString(strModulePath);
        if (!bRet) break;

        //
        //  APC 注入
        //

        do
        {
            if (te32.th32OwnerProcessID == m_dwProcessId)
            {
                if (!te32.th32ThreadID) continue;

                hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
                if (!hThread) continue;
                QueueUserAPC((PAPCFUNC)LoadLibraryW, hThread, (ULONG_PTR)pVa);
                CloseHandle(hThread);
                hThread = nullptr;
            }
        } while (Thread32Next(hSnapShot, &te32));

        bSuccess = TRUE;

    } while (FALSE);

    if (pVa)
        VirtualFreeEx(hProcess, pVa, 0x100, MEM_RELEASE);

    if (hProcess)
        CloseHandle(hProcess);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));

    RefreshModuleList();
}

void CInjectorDlg::HijackInject()
{
    UpdateData(TRUE);
    m_SelectImageDlg.DoModal();

    if (m_strProcessImage.IsEmpty())
    {
        AfxMessageBox(_T("进程映像未指定"));
        return;
    }

    if (m_strDllPath.IsEmpty())
    {
        AfxMessageBox(_T("请选择模块"));
        return;
    }

    BSTR strImagePath = nullptr; 
    BSTR strModulePath = nullptr; 
    BOOL bRet;
    BOOL bSuccess = FALSE;
    STARTUPINFO si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    LPVOID lpAddress = nullptr;
    SIZE_T BytesWritten;
    HANDLE hRemoteThread = nullptr;

    si.cb = sizeof(STARTUPINFO);

    do
    {
        //
        //  创建进程
        //

        strImagePath = m_strProcessImage.AllocSysString();
        bRet = CreateProcess(strImagePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
        ::SysFreeString(strImagePath);
        if (!bRet) break;

        //
        //  写入模块的绝对路径
        //

        lpAddress = VirtualAllocEx(pi.hProcess, NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if (!lpAddress) break;

        strModulePath = m_strDllPath.AllocSysString();
        bRet = WriteProcessMemory(pi.hProcess, lpAddress, strImagePath, ((wcslen(strImagePath) + 1) * 2), &BytesWritten);
        ::SysFreeString(strModulePath);
        if (!bRet) break;

        //
        //  远线程注入
        //

        hRemoteThread = CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddress, NULL, NULL);
        ResumeThread(pi.hThread);
        WaitForSingleObject(hRemoteThread, 1000);

        m_dwProcessId = pi.dwProcessId;
        UpdateData(FALSE);
        bSuccess = TRUE;

    } while (FALSE);

    if (hRemoteThread)
        CloseHandle(hRemoteThread);

    if (lpAddress)
        VirtualFreeEx(pi.hProcess, lpAddress, 0, MEM_RELEASE);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));

    RefreshModuleList();
}

void CInjectorDlg::MessageHookInject(IN LPCSTR FunctionName)
{
    UpdateData(TRUE);

    if (m_strDllPath.IsEmpty())
    {
        AfxMessageBox(_T("请选择模块"));
        return;
    }

    BOOL bSuccess = FALSE;
    HMODULE hModule;
    HOOKPROC FunctionAddress;
    BOOL bRet;
    DWORD dwThreadId = 0;
    HHOOK hHook;

    do
    {
        hModule = LoadLibraryEx(m_strDllPath.GetBuffer(0), nullptr, DONT_RESOLVE_DLL_REFERENCES);
        if (!hModule) break;

        FunctionAddress = (HOOKPROC)GetProcAddress(hModule, FunctionName);
        if (!FunctionAddress) break;

        m_hMainWindow = nullptr;
        bRet = EnumWindows(EnumWindowsProcAdapter, (LPARAM)this);
        if (!m_hMainWindow) break;

        dwThreadId = GetWindowThreadProcessId(m_hMainWindow, nullptr);
        if (!dwThreadId) break;

        hHook = SetWindowsHookEx(WH_KEYBOARD, FunctionAddress, hModule, dwThreadId);
        if (!hHook) break;

        bSuccess = TRUE;

    } while (FALSE);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));

    RefreshModuleList();
}

void CInjectorDlg::PeInject()
{
    UpdateData(TRUE);

    m_SelectImageDlg.DoModal();
    if (m_strProcessImage.IsEmpty())
    {
        AfxMessageBox(_T("进程映像未指定"));
        return;
    }

    HANDLE hProcess = nullptr;
    HMODULE hModule = nullptr;
    DWORD dwImageSize;
    LPVOID lpCodeAddress = nullptr;
    LPVOID lpParamAddress = nullptr;
    LPVOID lpRecoverAddress = nullptr;
    LPVOID lpImage = nullptr;
    BOOL bSuccess = FALSE;
    BOOL bRet;
    DWORD RvaOfText;
    DWORD SizeOfText;
    REMOTE_PARAMS Params;
    HMODULE Kernel32Base;
    HANDLE hRemoteThread;

    do
    {
        //
        //  加载映像
        //

        hModule = LoadLibraryEx(m_strProcessImage.GetBuffer(0), nullptr, DONT_RESOLVE_DLL_REFERENCES);
        if (!hModule) break;
        dwImageSize = GetImageSize((LPVOID)hModule);

        bRet = GetRvaOfTextAndSize((LPVOID)hModule, &RvaOfText, &SizeOfText);
        if (!bRet) break;

        //
        //  获取目标进程句柄
        //

        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
        if (!hProcess) break;

        //
        //  申请虚拟内存空间
        //

        lpCodeAddress = VirtualAllocEx(hProcess, nullptr, dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!lpCodeAddress) break;

        //
        //  申请修复导入表代码内存
        //

        lpParamAddress = VirtualAllocEx(hProcess, nullptr, sizeof(REMOTE_PARAMS), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!lpParamAddress) break;
        Kernel32Base = LoadLibraryA("Kernel32.dll");
        Params.ImageBase = (LongPtr)lpCodeAddress;
        Params._GetProcAddress = (FnGetProcAddress)GetProcAddress(Kernel32Base, "GetProcAddress");
        Params._LoadLibraryA = (FnLoadLibraryA)GetProcAddress(Kernel32Base, "LoadLibraryA");
        Params._VirtualProtect = (FnVirtualProtect)GetProcAddress(Kernel32Base, "VirtualProtect");
        Params._ExitThread = (FnExitThread)GetProcAddress(Kernel32Base, "ExitThread");

        bRet = WriteProcessMemory(hProcess, lpParamAddress, &Params, sizeof(REMOTE_PARAMS), nullptr);
        if (!bRet) break;

        lpRecoverAddress = VirtualAllocEx(hProcess, nullptr, (SIZE_T)((SIZE_T)RecoverRelocationEntry - (SIZE_T)RecoverIAT), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!lpRecoverAddress) break;

        bRet = WriteProcessMemory(hProcess, lpRecoverAddress, RecoverIAT, (SIZE_T)((SIZE_T)RecoverRelocationEntry - (SIZE_T)RecoverIAT), nullptr);
        if (!bRet) break;

        //
        //  重定位映像文件
        //

        lpImage = RelocateImage((LPVOID)hModule, dwImageSize, (LongPtr)lpCodeAddress);
        if (!lpImage) break;

        bRet = WriteProcessMemory(hProcess, lpCodeAddress, lpImage, dwImageSize, nullptr);
        if (!bRet) break;

        //
        //  执行
        //

        hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)(lpRecoverAddress), lpParamAddress, 0, NULL);
        if (!hRemoteThread) break;
        WaitForSingleObject(hRemoteThread, INFINITE);

        CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((char*)lpCodeAddress + RvaOfText), NULL, 0, NULL);

        bSuccess = TRUE;

    } while (FALSE);

    if (!bSuccess)
    {
        if (lpCodeAddress)
            VirtualFreeEx(hProcess, lpCodeAddress, dwImageSize, MEM_RELEASE);

        if (lpRecoverAddress)
            VirtualFreeEx(hProcess, lpRecoverAddress, (SIZE_T)((SIZE_T)RecoverRelocationEntry - (SIZE_T)RecoverIAT), MEM_RELEASE);

        if (lpParamAddress)
            VirtualFreeEx(hProcess, lpParamAddress, sizeof(REMOTE_PARAMS), MEM_RELEASE);

        if (hProcess)
            CloseHandle(hProcess);
    }

    if (lpImage)
        VirtualFree(lpImage, dwImageSize, MEM_RELEASE);

    if (hModule)
        FreeLibrary(hModule);
}

BOOL CInjectorDlg::PreRemoteThreadInjectCode(OUT PHANDLE hProcess)
{
    BOOL bRet = FALSE;
    ULONG_PTR Address = INJECT_ADDRESS;

    do
    {
        //
        //  获得目标进程句柄
        //

        *hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
        if (!(*hProcess)) break;

        //
        //  申请虚拟内存空间
        //

        m_lpCodeAddress = VirtualAllocEx(*hProcess, (LPVOID)Address, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!m_lpCodeAddress)
        {
            m_lpCodeAddress = VirtualAllocEx(*hProcess, nullptr, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if (!m_lpCodeAddress) break;
        }

        bRet = TRUE;

    } while (FALSE);

    return bRet;
}

void CInjectorDlg::PostRemoteThreadInjectCode(IN HANDLE hProcess, IN PVOID Code, IN SIZE_T Len)
{
    SIZE_T BytesWritten = 0;
    BOOL bRet;
    HANDLE hRemoteThread = nullptr;
    BOOL bSuccess = FALSE;
    PVOID pCode = Code;
    SIZE_T stCodeLen = Len;

    do
    {
        //
        //  写入 Shellcode
        //

        bRet = WriteProcessMemory(hProcess, m_lpCodeAddress, pCode, stCodeLen, &BytesWritten);
        if (!bRet) break;

        //
        //  远程线程执行
        //

        hRemoteThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)m_lpCodeAddress, nullptr, 0, nullptr);
        WaitForSingleObject(hRemoteThread, 1000);

        bSuccess = TRUE;

    } while (FALSE);

    if (hProcess)
        CloseHandle(hProcess);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));
}

BOOL CInjectorDlg::PreEarlyBirdInjectCode(OUT PHANDLE hProcess, OUT PHANDLE hThread)
{
    UpdateData(TRUE);
    m_SelectImageDlg.DoModal();

    if (m_strProcessImage.IsEmpty())
    {
        AfxMessageBox(_T("进程映像未指定"));
        return FALSE;
    }

    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    PROCESS_INFORMATION pi = { 0 };
    BOOL bRet = FALSE;

    do
    {
        bRet = CreateProcess(m_strProcessImage.GetBuffer(0), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
        if (!bRet) break;

        m_lpCodeAddress = VirtualAllocEx(pi.hProcess, NULL, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if (!m_lpCodeAddress)
        {
            bRet = FALSE;
            break;
        }

        *hProcess = pi.hProcess;
        *hThread = pi.hThread;

        bRet = TRUE;

    } while (FALSE);

    return bRet;
}

void CInjectorDlg::PostEarlyBirdInjectCode(IN HANDLE hProcess, IN HANDLE hThread, IN PVOID Code, IN SIZE_T Len)
{
    BOOL bRet;
    BOOL bSuccess = FALSE;
    SIZE_T stBytesReturn;

    do
    {
        bRet = WriteProcessMemory(hProcess, m_lpCodeAddress, Code, Len, &stBytesReturn);
        if (!bRet) break;

        bRet = QueueUserAPC((PAPCFUNC)m_lpCodeAddress, hThread, 0);
        if (!bRet) break;

        ResumeThread(hThread);

        bSuccess = TRUE;

    } while (FALSE);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));
}

BOOL CInjectorDlg::PreCtrlInjectCode(OUT PHANDLE hProcess)
{
    BOOL bRet = FALSE;
    ULONG_PTR Address = INJECT_ADDRESS;

    do
    {
        //
        //  获取要用到的函数地址
        //

        if (!_RtlEncodeRemotePointer)
        {
            _RtlEncodeRemotePointer = (FnRtlEncodeRemotePointer)GetFunctionAddress("ntdll.dll", "RtlEncodeRemotePointer");
            if (!_RtlEncodeRemotePointer) break;
        }

        if (!_RtlDecodeRemotePointer)
        {
            _RtlDecodeRemotePointer = (FnRtlDecodeRemotePointer)GetFunctionAddress("ntdll.dll", "RtlDecodeRemotePointer");
            if (!_RtlDecodeRemotePointer) break;
        }

        if (!_SetProcessValidCallTargets)
        {
            _SetProcessValidCallTargets = (FnSetProcessValidCallTargets)GetFunctionAddress("kernelbase.dll", "SetProcessValidCallTargets");
            if (!_SetProcessValidCallTargets) break;
        }

        if (!m_pSetConsoleCtrlHandler)
        {
            m_pSetConsoleCtrlHandler = GetFunctionAddress("kernelbase.dll", "SetConsoleCtrlHandler");
            if (!m_pSetConsoleCtrlHandler) break;
        }

        //
        //  获得目标进程句柄
        //

        *hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
        if (!(*hProcess)) break;

        //
        //  申请虚拟内存空间
        //

        m_lpCodeAddress = VirtualAllocEx(*hProcess, (LPVOID)Address, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!m_lpCodeAddress)
        {
            m_lpCodeAddress = VirtualAllocEx(*hProcess, nullptr, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if (!m_lpCodeAddress) break;
        }

        bRet = TRUE;

    } while (FALSE);

    return bRet;
}

void CInjectorDlg::PostCtrlInjectCode(IN HANDLE hProcess, IN PVOID Code, IN SIZE_T Len)
{
    BOOL bRet;
    BOOL bSuccess = FALSE;
    SIZE_T stBytesReturn;
    HRESULT hResult;
    PVOID lpEncodeAddress;
    CFG_CALL_TARGET_INFO CfgCallTargetInfo = { 0 };
    MEMORY_BASIC_INFORMATION MemoryInfo = { 0 };

    do
    {
        //
        //  写入代码
        //

        bRet = WriteProcessMemory(hProcess, m_lpCodeAddress, Code, Len, &stBytesReturn);
        if (!bRet) break;

        //
        //  获取内存信息
        //

        stBytesReturn = VirtualQuery(m_lpCodeAddress, &MemoryInfo, sizeof(MEMORY_BASIC_INFORMATION));
        if (!stBytesReturn) break;

        //
        //  编码指针
        //

        hResult = _RtlEncodeRemotePointer(hProcess, m_lpCodeAddress, &lpEncodeAddress);
        if (S_OK != hResult) break;

        //
        //  通知远程进程有效指针
        //

        CfgCallTargetInfo.Flags = CFG_CALL_TARGET_VALID;
        CfgCallTargetInfo.Offset = (ULONG_PTR)m_lpCodeAddress - (ULONG_PTR)MemoryInfo.AllocationBase;
        bRet = _SetProcessValidCallTargets(hProcess, lpEncodeAddress, PAGE_SIZE, 0x1, &CfgCallTargetInfo);
        //if (!bRet) break;

        //
        //  触发 Ctrl+C
        //

        m_hMainWindow = nullptr;
        bRet = EnumWindows(EnumWindowsProcAdapter, (LPARAM)this);
        if (!m_hMainWindow) break;

        TriggerCtrlC(m_hMainWindow);

        bSuccess = TRUE;

    } while (FALSE);

    if (bSuccess)
        AfxMessageBox(_T("注入成功"));
    else
        AfxMessageBox(_T("注入失败"));
}

void CInjectorDlg::RefreshModuleList()
{
    m_ModuleList.DeleteAllItems();
    InitializeModuleList();
}

void CInjectorDlg::OnBnClickedBtnInject()
{
    m_SelectInjectDlg.DoModal();
    if (!m_pInjectConfig->bConfirm) return;

    switch (m_pInjectConfig->Type)
    {
    case M_REMOTE_THREAD:
        RemoteThreadInject();
        break;
    case M_USER_APC:
        UserApcInject();
        break;
    case M_HIJACK:
        HijackInject();
        break;
    case M_MESSAGE_HOOK:
    {
        MessageHookInject((LPCSTR)m_pInjectConfig->Data);

        if (m_pInjectConfig->Data)
            delete[] m_pInjectConfig;
        break;
    }
    case M_PE_INJECT:
    {
        PeInject();
        break;
    }
    default:
        break;
    }
}

void CInjectorDlg::OnNMRClickListModule(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    POINT Point = { 0 };
    CMenu RightMenu;
    CMenu* pSubMenu;

    GetCursorPos(&Point);
    RightMenu.LoadMenu(MAKEINTRESOURCE(IDR_RIGHTMENU_MODULELIST));
    pSubMenu = RightMenu.GetSubMenu(0);
    pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, Point.x, Point.y, this);

    *pResult = 0;
}

void CInjectorDlg::OnRightmenuRefreshlist()
{
    RefreshModuleList();
}

void CInjectorDlg::OnRightmenuRemovemodule()
{
    int nSel;
    CString strDllName;
    BSTR wcDllName = nullptr;
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32 = {};
    HMODULE hModule = nullptr;
    HANDLE hProcess = nullptr;
    LPTHREAD_START_ROUTINE lpFreeLibrary;
    HANDLE hRemoteThread = nullptr;
    BOOL bSuccess = FALSE;

    do
    {
        //
        //  获取要卸载的模块名称
        //

        nSel = m_ModuleList.GetSelectionMark();
        if (-1 == nSel) break;
        strDllName = m_ModuleList.GetItemText(nSel, 0);
        wcDllName = strDllName.AllocSysString();

        //
        //  获取模块快照句柄
        //

        hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, m_dwProcessId);
        if (INVALID_HANDLE_VALUE == hSnapShot) break;

        //
        //  获取第一个模块信息
        //

        me32.dwSize = sizeof(MODULEENTRY32);
        if (!Module32First(hSnapShot, &me32)) break;

        //
        //  获取指定模块起始地址
        //

        do
        {
            if (!_tcsicmp(me32.szModule, wcDllName))
            {
                hModule = me32.hModule;
                break;
            }
        } while (Module32Next(hSnapShot, &me32));

        if (!hModule) break;

        //
        //  获得进程句柄
        //

        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId);
        if (!hProcess) break;

        //
        //  获取 FreeLibrary 函数地址
        //

        lpFreeLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "FreeLibrary");
        if (!lpFreeLibrary) break;

        //
        //  卸载模块
        //

        hRemoteThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)lpFreeLibrary, hModule, 0, nullptr);
        WaitForSingleObject(hRemoteThread, 1000);

        bSuccess = TRUE;

    } while (FALSE);

    if (hRemoteThread)
        CloseHandle(hRemoteThread);

    if (hProcess)
        CloseHandle(hProcess);

    if (INVALID_HANDLE_VALUE != hSnapShot)
        CloseHandle(hSnapShot);

    if (wcDllName)
        ::SysFreeString(wcDllName);

    if (bSuccess)
        AfxMessageBox(_T("卸载成功"));
    else
        AfxMessageBox(_T("卸载失败"));

    RefreshModuleList();
}

void CInjectorDlg::OnBnClickedBtnShellcodeinject()
{
    UpdateData(TRUE);
    HANDLE hProcess = nullptr;
    HANDLE hThread = nullptr;
    BOOL bRet = FALSE;

    m_SelectInjectDlg2.DoModal();
    if (m_CodeInjectType == UNKNOWN_TYPE) return;

    //
    //  Pre
    //

    switch (m_CodeInjectType)
    {
    case S_REMOTE_THREAD:
        bRet = PreRemoteThreadInjectCode(&hProcess);
        break;
    case S_EARLY_BIRD:
        bRet = PreEarlyBirdInjectCode(&hProcess, &hThread);
        break;
    case S_CTRL_C:
        bRet = PreCtrlInjectCode(&hProcess);
        break;
    default:
        break;
    }
    if (!bRet) return;

    m_ShellcodeDlg.DoModal();
    if (!m_pShellCodeConfig->bConfirm) return;

    //
    //  Post
    //

    switch (m_CodeInjectType)
    {
    case S_REMOTE_THREAD:
        PostRemoteThreadInjectCode(hProcess, m_pShellCodeConfig->Code, m_pShellCodeConfig->CodeLen);
        break;
    case S_EARLY_BIRD:
        PostEarlyBirdInjectCode(hProcess, hThread, m_pShellCodeConfig->Code, m_pShellCodeConfig->CodeLen);
        break;
    case S_CTRL_C:
        PostCtrlInjectCode(hProcess, m_pShellCodeConfig->Code, m_pShellCodeConfig->CodeLen);
        break;
    default:
        break;
    }

    delete[] (m_pShellCodeConfig->Code);
}
